package states;

import java.io.Serializable;

import hypeerweb.*;
/** 
 * Description of NodeState
* 
*
* @author Ike Ellsworth
*/
public abstract class NodeState implements Serializable {
    /**
     * returns a NodeState
     * 
     * Based on a given integer, it returns the singleton of the
     * appropriate NodeState subclass, creating it if it doesn't 
     * yet exist.
     * 
     * @param id int
     * @return NodeState
     * 
     * @pre <i>0 <= id < 2</i>
     * @post <i>creates a singleton for the state if none existed.</i>
     */
    public static NodeState getNodeState(int id)
    {
        switch(id)
        {
        case 0: return StandardNodeState.getSingleton();
        case 1: return DownPointingNodeState.getSingleton();
        case 2: return HypercubeCapState.getSingleton();
        default: return null;
        }
    }
    /**
     * returns an int representing what state it is.
     * 
     * Each NodeState subclass contains a static int STATE_ID.  This 
     * method returns that STATE_ID, which can then be used to test
     * what state you are in.  This is an abstract method that is overridden 
     * in each of the subclasses.
     *  
     * @return 0 if StandardNodeState, 1 if DownPointingNodeState, 2 if HypercubeCapState
     * 
     * @pre <i>None</i>
     * @post <i>None</i>
     */
    public abstract int getId();
    /**
     * returns the next NodeState
     * 
     * returns the next NodeState for the given NodeState when we add
     * a child or neighbor to the Node n.  This is an abstract method 
     * that is overridden in each of the subclasses, and behaves differently 
     * in each of them.
     *  
     * @param n Node representing the current node that is in this state.
     * @return a NodeState, representing what the next NodeState is.
     * 
     * @pre <i>Node n is in the NodeState that this method is called on.</i>
     * @post <i>Node n and the current NodeState are not changed.</i>
     */
    public abstract NodeState getNextNodeState(Node n);
    /**
     * returns the NodeState of the child.
     * 
     * returns the NodeState that should belong to a child of a 
     * Node that is currently in the current NodeState.  This is 
     * an abstract method that is overridden in each of the subclasses, 
     * and behaves differently in each one.
     *  
     * @return a NodeState, representing the state of the child.
     * 
     * @pre <i>None</i>
     * @post <i>the current NodeState is not altered.</i>
     */
    public abstract NodeState getChildNodeState();
    /**
     * returns the NodeState of the parent.
     * 
     * returns the NodeState that should belong to a parent of a 
     * Node that is currently in the current NodeState.  This is 
     * an abstract method that is overridden in each of the subclasses, 
     * and behaves differently in each one.
     *  
     * @return a NodeState, representing the state of the parent.
     * 
     * @pre <i>None</i>
     * @post <i>the current NodeState is not altered.</i>
     */
    public abstract NodeState getParentNodeState();
    /**
     * returns the NextNode that we should visit when searching for the cap node.
     * 
     * searches either the neighbors or down pointers of Node n to 
     * determine what Node we should visit next.  This is an abstract method
     * that behaves differently in each subclass.
     *  
     * @param n Node representing the current Node.
     * @return a Node, representing the next Node we should visit.
     * 
     * @pre <i>n is in the current NodeState</i>
     * @post <i>n is not altered, neither is the current NodeState</i>
     */
    public abstract Node getNextNode(Node n);
    /**
     * converts the NodeState into a string
     * 
     * @return a String representing the current NodeState.
     * 
     * @pre <i>None</i>
     * @post <i>None</i>
     */
    public abstract String toString();
}
